#ifndef LEVEL_PARSER_H
#define LEVEL_PARSER_H


#include <fstream>
#include <iostream>
#include <string>
#include <regex>
#include <vector>

#include "../containers/sprite.h"
#include "../containers/layer.h"
#include "../subsystems/graphics.h"

enum class LevelToken {
	INVALID = 0, EMPTY, COMMENT,
	DESCRIPTOR_DRAWABLE, DESCRIPTOR_PLAYER, DESCRIPTOR_IMAGE, DESCRIPTOR_TEXT,
	LAYER, ATLAS, SOURCE, OFFSET, SCALE, SCALE_MULT,
	MOVES, DRAWABLE, PLAYER, IMAGE, TEXT, PATH
};

class LevelParser {
public:
	LevelParser(std::string path);
	~LevelParser();

	bool dry_run();
	std::vector<Layer> parse(Graphics& graphics);
private:
	std::ifstream file;
	std::smatch mode;
	const std::vector<std::pair<std::regex, LevelToken>> matchings {
		{ std::regex(R"(^ *$)"),                                                              LevelToken::EMPTY },
		{ std::regex(R"(^#.+$)"),                                                             LevelToken::COMMENT },
		{ std::regex(R"(^drawable$)"),                                                        LevelToken::DESCRIPTOR_DRAWABLE },
		{ std::regex(R"(^player$)"),                                                          LevelToken::DESCRIPTOR_PLAYER },
		{ std::regex(R"(^image$)"),                                                           LevelToken::DESCRIPTOR_IMAGE },
		{ std::regex(R"(^text$)"),                                                            LevelToken::DESCRIPTOR_TEXT },
		{ std::regex(R"(^layer$)"),                                                           LevelToken::LAYER },
		{ std::regex(R"(^atlas .*$)"),                                                        LevelToken::ATLAS },
		{ std::regex(R"(^source .*$)"),                                                       LevelToken::SOURCE },
		{ std::regex(R"(^offset (\\+|-)?[[:digit:]]+ (\\+|-)?[[:digit:]]+$)"),                LevelToken::OFFSET },
		{ std::regex(R"(^scale (\\+|-)?[[:digit:]]+ (\\+|-)?[[:digit:]]+$)"),                 LevelToken::SCALE },
		{ std::regex(R"(^scale [+-]?([0-9]*[.])?[0-9]+$)"),                                   LevelToken::SCALE_MULT },
		{ std::regex(R"(^moves (false|true)$)"),                                              LevelToken::MOVES },
		{ std::regex(R"(^((\\+|-)?[[:digit:]]+ ){2}(\\+|-)?[[:digit:]]+$)"),                  LevelToken::DRAWABLE },
		{ std::regex(R"(^((\\+|-)?[[:digit:]]+ ){5}(\\+|-)?[[:digit:]]+$)"),                  LevelToken::PLAYER },
		{ std::regex(R"(^(\\+|-)?[[:digit:]]+ (\\+|-)?[[:digit:]]+ path .*$)"),               LevelToken::IMAGE },
		{ std::regex(R"(^(\\+|-)?[[:digit:]]+ (\\+|-)?[[:digit:]]+ 0[xX][0-9a-fA-F]{8} (small|medium|big) .*$)"), LevelToken::TEXT }
	};

	LevelToken match_token(std::string line);
};

#endif